<?php
declare(strict_types=1);

namespace Service\FaceService;

use Service\BaseService;
use Service\Code\Normal;
use Service\ExtraService\TaskWorker;

/**
 * 中盾服务接口
 * @author chenshubo
 */
class CTIDService extends BaseService
{
    const cipher    = 'AES-128-CBC';
    const authmode  = '0x42';
    const biztype   = 6000;
    protected $config = [
        'orgcode'       => '9cc9783c899a4bbea6a211df59024a46',
        'private_key'   => 'MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAI+iprUAz5iAyW4H7sfuDQPzOiCzxu3IN20pTKSqZ4g7+P1XgyA14z2uGCjVnMH3PSHypGnhSX2ktNMiig36Q8SdXzguXC21UxuIyBxsUYkxXlRxtKf+Z+yB+QazToaKfIZfi9Q50ESG+psf6g2HXRB+wLh+Rzl7VKx5ZUEYqRU9AgMBAAECgYARADJ1KBRqO4wb7upvVZjKx+Ywarb3/AO7cvD0aIr6kAanjc0iad5stYd8hdQZDTd6JisZsSWurmkMuIDYqK+Oj3HIppPEG3LxtmJWSdoCHuuz7Mcm3U4RLXqwjhOEZtgEQ8ERTxYspzUDrA4GywQF4HIwJLWGXM3mblHjMnfQgQJBANHfy+hpzw/HzlM6D4MLuvpk0xObdytuYtTE05UEbn6/CpnEhsjxU9dhYLzusklZdOqtGZi/1Pw2NhzvOfXZ3l0CQQCvNArOGeJRv82cY43YdvJ0KsAF+rVQWnM3hYQ+/hLRzpuxiXyhGr/L9WhsO4SoryAAdF1Khv6CFJ6u0xxYReRhAkEAvWRM+WYKgj4X1gkuGF8Mk4tK44XHC71omIMqQG6oW96AbXTpAQquU02/458v6ns8w84DrFFonVU6je/gCRlbzQJAP2rNBnEkFIciu5rlexcDB715qDBpdN5omg5AIjUBRuRMQuULMZ1nE0KPO64HhK9vG/sC0bkvYpJoJcvQlLsnwQJAAvKcN+I3+KIVKBjD0M3gjieoqtLT0ugeqnZrThk8vf0CuXX6qD22ch/aAi0A57BOfsTUGRtW69cA+fZcptEJrA==',
        'public_key'    => 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCl23X1jCttl9A93NT1Uev8/5rXZezm83BwbJKQQFi8onP7lBRTBQh8/ahyhMX8Qc2QKEq4/t58Q0NVZE2/Yb8OqZk4LEu1pCt2ra57DSvgMQ41oxDere4kyTYAqFuMJoQQgEmyYpzpHQu1GlSYRtbJ3Oxd/JqHfOSjPVYJaDEBswIDAQAB'
    ];
    
    /**
     * 路由地址管理
     * @var unknown
     */
    protected $router = [
        'apply'     => 'http://api.easyctid.cn/v1/apply',
        'verify'    => 'http://api.easyctid.cn/ctid/v1/verification'
    ];
    
    /**
     * 校验人脸和身份证信息功能
     * @param array $param
     * @return type
     */
    public function checkFaceAndIdCard(array $param) 
    {
        if( empty($param['cardNo']) ) {
            return Normal::returnCode(Normal::FAIL,"身份证号cardNo不能为空");
        }
        
        if( empty($param['cardName']) ) {
            return Normal::returnCode(Normal::FAIL,"真实姓名cardName不能为空");
        }
        
        if( empty($param['photoData']) ) {
            return Normal::returnCode(Normal::FAIL,"面部人脸信息photoData不能为空");
        }
        
        // 填充bizPckage
        $bizPackage = [
            'orgCode'   => $this->config['orgcode'],
            'bizType'   => self::biztype,
            'bizData'   => [
                'authMode'=> self::authmode
            ]
        ];
        $result = $this->execute('apply',$bizPackage);
        if( $result['code'] != Normal::SUC ) {
            return $result;
        }
        
        $bizPackage     = $result['data'];
        $bizData        = $bizPackage['bizData'];
        $bsn            = $bizData['bsn'];
        $randomNumber   = $bizData['randomNumber'];
        
        // 两项信息
        $authApplyRetainData = [
            'name' => $param['cardName'],
            'idNo' => $param['cardNo']
        ];
        // 转为json
        $authApplyRetainData = json_encode($authApplyRetainData);
        // 加密
        $authApplyRetainData = $this->encrypt($authApplyRetainData,$this->config['public_key']);
        // 使用base64编码
        $authApplyRetainData = base64_encode($authApplyRetainData);
        // 填充bizPackage
        $bizPackage = [
            'orgCode'       => $this->config['orgcode'],
            'bizType'       => self::biztype,
            'bizData'       => [
                'authMode'              => self::authmode,
                'photoData'             => $param['photoData'],
                'authApplyRetainData'   => $authApplyRetainData
            ],
            'bsn'           => $bsn,
            'randomNumber'  => $randomNumber
        ];
        return $this->execute('verify',$bizPackage);
    }
    
    /**
     * @param string $method
     * @param array $param
     */
    public function execute(string $method,array $param)
    {
        $url = $this->router[$method];
        // 生成bizPackage的json字符串
        $bizPackage = json_encode($param);
        // 对bizPackage进行签名，并使用base64编码
        $sign       = $this->getSign($bizPackage,$this->config['private_key']);
        $sign       = base64_encode($sign);
        // 生成完整请求参数
        $postdata = [
            'bizPackage'    => $bizPackage,
            'sign'          => $sign
        ];
        
        $parameter = [
            [
                'tag'       => 'ctid_'.$method,
                'url'       => $url,
                'data'      => $postdata,
                'method'    => 'post',
                'format'    => 'json',
                'header'    => [
                ],
            ],
        ];
        $resTask = TaskWorker::instance()->addTask($parameter);
        $resTask = current($resTask);
        $response = json_decode($resTask['response']['result'],true);
        if( empty($response['bizPackage']) ) {
            return Normal::returnCode(Normal::FAIL,"bizPackage包体申请失败!");
        }
        
        // 获取bsn、randomNumber
        $bizPackage = json_decode($response['bizPackage'],true);
        if( !isset($bizPackage['resultCode']) ) {
            return Normal::returnCode(Normal::FAIL,"bizPackage包体resultCode不存在!");
        }
        
        if( $bizPackage['resultCode'] != '0' ) {
            return Normal::returnCode(Normal::FAIL,"bizPackage包体申请失败,原因：【{$bizPackage['resultDesc']}】");
        }
        
        return Normal::returnCode(Normal::SUC,"请求OK",$bizPackage);
    }

    /**
     * rsa加密
     */
    public function rsaEncrypt($content,$publicKey)
    {
        $publicKey = "-----BEGIN PUBLIC KEY-----\n" . wordwrap($publicKey, 64, "\n", true) . "\n-----END PUBLIC KEY-----";
        $key = openssl_get_publickey($publicKey);
        $out = '';
        openssl_public_encrypt($content,$out,$key);
        return $out;
    }
    
    //生成 sha256WithRSA 签名
    public function getSign($content, $privateKey)
    {
        $privateKey = "-----BEGIN RSA PRIVATE KEY-----\n" .
            wordwrap($privateKey, 64, "\n", true) .
            "\n-----END RSA PRIVATE KEY-----";
        $key = openssl_get_privatekey($privateKey);
        openssl_sign($content, $signature, $key, "SHA256");
        openssl_free_key($key);
        return $signature;
    }
    
    /**
     * aes加密
     */
    public function aesEncrypt($input, $key, $iv) {
        $data = openssl_encrypt($input, self::cipher, $key, OPENSSL_RAW_DATA, $iv);
        return $data;
    }
    
    /**
     * 提取公钥
     * @param string $content
     * @param string $key
     */
    public function encrypt(string $content,string $key) 
    {
        $len        = openssl_cipher_iv_length(self::cipher);
        $aesKey     = openssl_random_pseudo_bytes($len);
        $aesIv      = openssl_random_pseudo_bytes($len);
        $aesInfo    = $aesKey . $aesIv;
        $aesInfo    = $this->rsaEncrypt($aesInfo,$key);
        $aesEnData  = $this->aesEncrypt($content,$aesKey,$aesIv);
        return $aesInfo . $aesEnData;
    }
}
